#pragma once
#include <format>
#include <vulkan/vulkan.h>

template <> struct std::formatter<VkResult> : std::formatter<std::string_view> {
  auto parse(format_parse_context &ctx) {
    return std::formatter<std::string_view>::parse(ctx);
  }

  auto format(VkResult result, format_context &ctx) const {
    using namespace std::literals;
    switch (result) {
    case VK_SUCCESS:
      return std::formatter<std::string_view>::format("VK_SUCCESS", ctx);
    case VK_NOT_READY:
      return std::formatter<std::string_view>::format("VK_NOT_READY", ctx);
    case VK_TIMEOUT:
      return std::formatter<std::string_view>::format("VK_TIMEOUT", ctx);
    case VK_EVENT_SET:
      return std::formatter<std::string_view>::format("VK_EVENT_SET", ctx);
    case VK_EVENT_RESET:
      return std::formatter<std::string_view>::format("VK_EVENT_RESET", ctx);
    case VK_INCOMPLETE:
      return std::formatter<std::string_view>::format("VK_INCOMPLETE", ctx);
    case VK_SUBOPTIMAL_KHR:
      return std::formatter<std::string_view>::format("VK_SUBOPTIMAL_KHR", ctx);
    case VK_ERROR_OUT_OF_HOST_MEMORY:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_OUT_OF_HOST_MEMORY", ctx);
    case VK_ERROR_OUT_OF_DEVICE_MEMORY:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_OUT_OF_DEVICE_MEMORY", ctx);
    case VK_ERROR_INITIALIZATION_FAILED:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INITIALIZATION_FAILED", ctx);
    case VK_ERROR_DEVICE_LOST:
      return std::formatter<std::string_view>::format("VK_ERROR_DEVICE_LOST",
                                                      ctx);
    case VK_ERROR_MEMORY_MAP_FAILED:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_MEMORY_MAP_FAILED", ctx);
    case VK_ERROR_LAYER_NOT_PRESENT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_LAYER_NOT_PRESENT", ctx);
    case VK_ERROR_EXTENSION_NOT_PRESENT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_EXTENSION_NOT_PRESENT", ctx);
    case VK_ERROR_FEATURE_NOT_PRESENT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_FEATURE_NOT_PRESENT", ctx);
    case VK_ERROR_INCOMPATIBLE_DRIVER:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INCOMPATIBLE_DRIVER", ctx);
    case VK_ERROR_TOO_MANY_OBJECTS:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_TOO_MANY_OBJECTS", ctx);
    case VK_ERROR_FORMAT_NOT_SUPPORTED:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_FORMAT_NOT_SUPPORTED", ctx);
    case VK_ERROR_FRAGMENTED_POOL:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_FRAGMENTED_POOL", ctx);
    case VK_ERROR_UNKNOWN:
      return std::formatter<std::string_view>::format("VK_ERROR_UNKNOWN", ctx);
    case VK_ERROR_OUT_OF_POOL_MEMORY:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_OUT_OF_POOL_MEMORY", ctx);
    case VK_ERROR_INVALID_EXTERNAL_HANDLE:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INVALID_EXTERNAL_HANDLE", ctx);
    case VK_ERROR_FRAGMENTATION:
      return std::formatter<std::string_view>::format("VK_ERROR_FRAGMENTATION",
                                                      ctx);
    case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS", ctx);
    case VK_ERROR_SURFACE_LOST_KHR:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_SURFACE_LOST_KHR", ctx);
    case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR", ctx);
    case VK_ERROR_OUT_OF_DATE_KHR:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_OUT_OF_DATE_KHR", ctx);
    case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR", ctx);
    case VK_ERROR_VALIDATION_FAILED_EXT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_VALIDATION_FAILED_EXT", ctx);
    case VK_ERROR_INVALID_SHADER_NV:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INVALID_SHADER_NV", ctx);
    case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT", ctx);
    case VK_ERROR_NOT_PERMITTED_EXT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_NOT_PERMITTED_EXT", ctx);
    case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
      return std::formatter<std::string_view>::format(
          "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT", ctx);
    case VK_THREAD_IDLE_KHR:
      return std::formatter<std::string_view>::format("VK_THREAD_IDLE_KHR",
                                                      ctx);
    case VK_THREAD_DONE_KHR:
      return std::formatter<std::string_view>::format("VK_THREAD_DONE_KHR",
                                                      ctx);
    case VK_OPERATION_DEFERRED_KHR:
      return std::formatter<std::string_view>::format(
          "VK_OPERATION_DEFERRED_KHR", ctx);
    case VK_OPERATION_NOT_DEFERRED_KHR:
      return std::formatter<std::string_view>::format(
          "VK_OPERATION_NOT_DEFERRED_KHR", ctx);
    case VK_PIPELINE_COMPILE_REQUIRED_EXT:
      return std::formatter<std::string_view>::format(
          "VK_PIPELINE_COMPILE_REQUIRED_EXT", ctx);
    default:
      if (result >= 0) {
        return std::formatter<std::string_view>::format(
            std::format("Unknown success code ({})", static_cast<int>(result)),
            ctx);
      } else {
        return std::formatter<std::string_view>::format(
            std::format("Unknown error code ({})", static_cast<int>(result)),
            ctx);
      }
    }
  }
};
